package com.hxzy.consumer;

import com.hxzy.controller.OrderController;
import com.rabbitmq.client.Channel;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Log4j2
@Component
public class OrderDelayConsumer {

    @Autowired
    private RedisTemplate redisTemplate;


    @RabbitListener(queues = {"order_queue"})
    @RabbitHandler
    public void delayOrder(Message message, Channel channel) throws IOException {

        String orderId=new String(message.getBody());
        //查询数据库的值
        String redisKey = OrderController.CREATE_ORDER_KEY + orderId;

        //加入分布式锁（最简单的，最不可靠的）
        String lockKey = "lock:order:" + orderId;
        try {
            if (!this.redisTemplate.opsForValue().setIfAbsent(lockKey, 0, 60, TimeUnit.SECONDS)) {
                log.error("多线程操作同一笔订单，加锁不成功，释放订单无效");
            }


            Object redisValue = this.redisTemplate.opsForValue().get(redisKey);
            if (Objects.nonNull(redisValue)) {
                //取消订单
                Map<String, Object> map = (Map<String, Object>) redisValue;

                if (map.get("pay").equals(0)) {
                    log.info("----取消订单---");
                    //取消订单(删除数据的值)
                    this.redisTemplate.delete(redisKey);
                }
            }
            //消息要被消费(确认)
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

        } catch (Exception e) {
             log.error(e);
            //消息没有被消费(打回去)
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        } finally {
            this.redisTemplate.delete(lockKey);
        }
    }

}
